/**
 * 
 */
package com.dayatang.hrm.compensation.domain;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.hibernate.annotations.CollectionOfElements;

import com.dayatang.commons.domain.AbstractEntity;
import com.dayatang.commons.domain.InstanceFactory;
import com.dayatang.hrm.organisation.domain.Organization;
import com.dayatang.hrm.staffing.domain.Employee;

/**
 * 薪资档案
 * 
 * @author chencao
 * 
 */
@Entity
@Table(name = "pay_salary_archive")
public class SalaryArchive extends AbstractEntity {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6574772950370344989L;

	private static SalaryArchiveRepository salaryArchiveRepository;

	// 员工
	@ManyToOne
	@JoinColumn(name = "employee_id", nullable = false)
	private Employee employee;

	@ManyToOne
	@JoinColumn(name = "salary_payroll_id", nullable = false)
	private PayRoll payRoll;

	// 计算时间
	@Column(name = "calculate_time", nullable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date calculateTime;

	@CollectionOfElements
	@JoinTable(name = "pay_salary_archive_item", joinColumns = @JoinColumn(name = "salary_archive_id"))
	private Set<SalaryItemArchive> salaryItemArchives = new HashSet<SalaryItemArchive>();

	public SalaryArchive() {
	}

	public SalaryArchive(Employee employee, PayRoll payRoll, Date calculateTime) {
		this.employee = employee;
		this.payRoll = payRoll;
		this.calculateTime = calculateTime;
	}

	public static SalaryArchiveRepository getSalaryArchiveRepository() {
		if (salaryArchiveRepository == null) {
			salaryArchiveRepository = InstanceFactory
					.getInstance(SalaryArchiveRepository.class);
		}
		return salaryArchiveRepository;
	}

	public static void setSalaryArchiveRepository(
			SalaryArchiveRepository salaryArchiveRepository) {
		SalaryArchive.salaryArchiveRepository = salaryArchiveRepository;
	}

	public Employee getEmployee() {
		return employee;
	}

	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	public PayRoll getPayRoll() {
		return payRoll;
	}

	public void setPayRoll(PayRoll payRoll) {
		this.payRoll = payRoll;
	}

	public Date getCalculateTime() {
		return calculateTime;
	}

	public void setCalculateTime(Date calculateTime) {
		this.calculateTime = calculateTime;
	}

	// public Set<SalaryItemArchive> getSalaryItemArchives() {
	// return salaryItemArchives;
	// }

	public SortedSet<SalaryItemArchive> getSalaryItemArchives() {
		return new TreeSet<SalaryItemArchive>(salaryItemArchives);
	}

	public void setSalaryItemArchives(Set<SalaryItemArchive> salaryItemArchives) {
		this.salaryItemArchives = salaryItemArchives;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof SalaryArchive == false) {
			return false;
		}
		if (this == obj) {
			return true;
		}
		SalaryArchive rhs = (SalaryArchive) obj;
		return new EqualsBuilder().append(getId(), rhs.getId()).isEquals();
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder(17, 37).append(getId()).toHashCode();
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.SHORT_PREFIX_STYLE);
	}

	/*
	 * =======================================
	 * 
	 * action
	 * 
	 * ========================================
	 */

	public void save() {
		getSalaryArchiveRepository().save(this);
	}

	public void remove() {
		getSalaryArchiveRepository().remove(this);
	}

	public static SalaryArchive get(Long id) {
		return getSalaryArchiveRepository().get(id);
	}

	public void addSalaryItemArchive(SalaryItemArchive salaryItemArchive) {
		salaryItemArchives.add(salaryItemArchive);
	}

	/**
	 * 查找指定会计期间下，薪资帐套下的薪资档案集合
	 * 
	 * @param accountSuite
	 * @param fiscalPeriod
	 * @return
	 */
	public static List<SalaryArchive> findBySalaryAccountSuite(
			SalaryAccountSuite accountSuite, FiscalPeriod fiscalPeriod) {
		return getSalaryArchiveRepository().findBySalaryAccountSuite(
				accountSuite, fiscalPeriod);
	}

	/**
	 * 查找薪水册下的所有薪资档案集合
	 * 
	 * @param payRoll
	 * @return
	 */
	public static List<SalaryArchive> findByPayRoll(PayRoll payRoll) {
		return findBySalaryAccountSuite(payRoll.getSalaryAccountSuite(),
				payRoll.getFiscalPeriod());
	}

	/**
	 * 查找指定会计期间下，员工对应的薪资档案
	 * 
	 * @param employee
	 * @param fiscalPeriod
	 * @return
	 */
	public static SalaryArchive get(Employee employee, FiscalPeriod fiscalPeriod) {
		return getSalaryArchiveRepository().get(employee, fiscalPeriod);
	}

	/**
	 * 查找指定会计期间下，具体机构下的薪资档案集合
	 * 
	 * @param org
	 * @param includeSubsidiaries
	 * @param fiscalPeriod
	 * @return
	 */
	public static List<SalaryArchive> findByOrganization(Organization org,
			boolean includeSubsidiaries, FiscalPeriod fiscalPeriod) {
		// List<ActualSalaryArchive> archives = new
		// ArrayList<ActualSalaryArchive>();
		//
		// List<Employee> employees = Employee.findByOrganization(organization,
		// includeSubsidiaries, fiscalPeriod.getEndDate());
		//
		// if (employees != null && !employees.isEmpty()) {
		// for (Employee employee : employees) {
		// ActualSalaryArchive archive = get(employee, fiscalPeriod);
		// if (archive != null) {
		// archives.add(archive);
		// }
		// }
		// }
		//
		// return archives;
		return getSalaryArchiveRepository().findByOrganization(org,
				includeSubsidiaries, fiscalPeriod);
	}
}
